package main

import (
	"flag"
	"fmt"
	"reflect"

	"gitee.com/thubcc/blockchain/accounts"
	"gitee.com/thubcc/fmstream/p2p"
	"gitee.com/thubcc/mobile/fm"
	"gitee.com/thubcc/rtlmmap"
	"gitee.com/thubcc/rtlmmap/web"
	"github.com/gin-gonic/gin"
	"github.com/prometheus/common/log"
)

var (
	argTopic    = flag.String("topic", "44c7429f", "topic in hexadecimal format (e.g. 70a4beef)")
	argPass     = flag.String("password", "123456", "message's encryption password")
	argDataDir  = flag.String("dir", ".ethereum/chain", "ethereum data dir")
	argKeyPass  = flag.String("p", "931", "message's encryption password")
	argPrefix   = flag.String("u", "931", "address prefix")
	argMax      = flag.Int64("m", 1000000, "Max search")
	argAddr     = flag.String("addr", "0x69B47aD51691905D4ae1B3b61B27164C1776D08B", "contract address")
	argRFPort   = flag.Int("rf", 0, "RF antenna")
	argListen   = flag.Int("listen", 8080, "web listen port")
	enodeString = flag.String("n", p2p.DefaultNode, "enode")
)
var (
	port *web.Port
	maps = map[string]string{
		"open":    "Open",
		"suspend": "Suspend",
		"start":   "Start",
		"stop":    "Stop",
		"resume":  "Resume",
		"fc":      "SetFc",
		"gain":    "SetGain",
	}
	routers    = make(map[string]func(*gin.Context))
	postAction = map[string]func(){
		"Start": func() { systemStart() },
		"Stop":  func() { systemStop() },
	}
	broadcast *p2p.P2PFMer
	src       *fm.FM
)

func PortSpecificationAPI(name string) func(c *gin.Context) {
	return func(c *gin.Context) {
		getValue := reflect.ValueOf(port)
		methodValue := getValue.MethodByName(name)
		args := []reflect.Value{reflect.ValueOf(c)}
		methodValue.Call(args)
		if f, ok := postAction[name]; ok {
			f()
		}
	}
}
func Init() (r *gin.Engine, err error) {
	r = gin.Default()
	port, err = web.GlobPorts.GetPort(*argRFPort)
	if err != nil {
		return
	}
	routers["/list"] = web.GlobPorts.List
	for k, v := range maps {
		routers[fmt.Sprintf("/%s/:port", k)] = PortSpecificationAPI(v)
	}
	for k, v := range routers {
		r.GET(k, v)
	}
	return
}

func systemStart() {
	log.Info("Start ...")
	f := 200. / 1920.
	config := &rtlmmap.DefaultFMConfig
	view := rtlmmap.NewRtlView(0, config).FTV(0)
	view.ResetPPM()
	fafc := func(df float64) {
		ftco := view.View.GetFTco()
		_, dfr := ftco.GetTuner()
		ff := df / dfr
		ftco.PPMAbs(ff)
	}
	src = fm.NewFM(f, 4, view)
	src.AFC(false, fafc)

	keyConfig := accounts.NewConfig(*argDataDir, true, *argMax)
	prk, err := keyConfig.FindKey(*argPrefix, *argKeyPass)
	if err != nil {
		log.Error(err)
		return
	}
	var p2pconfig = &p2p.Config{*enodeString, prk}

	broadcast, err = p2p.NewP2PFMer(p2pconfig, web.GetOtoContext(), p2p.NilName("raw"))
	if err != nil {
		log.Error(err)
		return
	}
	broadcast.Run(*argTopic, *argPass)
	log.Info("server start")
	go src.StartWithOpus(broadcast)
}

func systemStop() {
	src.AFC(false, func(df float64) {})
	src.Close()
}

func main() {
	flag.Parse()
	// logHandler := elog.StreamHandler(os.Stdout, elog.JSONFormat())
	// elog.Root().SetHandler(elog.LvlFilterHandler(elog.Lvl(4), logHandler))

	r, err := Init()
	if err == nil {
		r.Run(fmt.Sprintf(":%d", *argListen))
	}
}
